package nl.utwente.ewi.hmi.multitouch.drivers.diamondtouch;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import nl.utwente.ewi.hmi.multitouch.TouchDeviceInfo;
import nl.utwente.ewi.hmi.multitouch.io.TouchStream;
import nl.utwente.ewi.hmi.multitouch.io.TouchStreamProvider;

import com.merl.diamondtouch.DtlibDevice;
import com.merl.diamondtouch.DtlibException;
import com.merl.diamondtouch.DtlibInputTframe;

/**
 * The DiamondTouchStreamProvider offers {@linkplain TouchDeviceInfo TouchDeviceInfos} for all connected
 * DiamondTouch devices.
 * 
 * @author Michiel Hakvoort
 * @version 1.0
 *
 */
public class DiamondTouchStreamProvider implements TouchStreamProvider {

	private static final List<TouchDeviceInfo> touchDeviceInfos;

	private static final Map<TouchDeviceInfo, TouchStream> registeredStreams;
	
	private static final DiamondTouchStreamProvider instance;
	
	private DiamondTouchStreamProvider() {		
	}
	
	public static DiamondTouchStreamProvider getDiamondTouchStreamProvider() {
		return instance;
	}
	
	static {
		instance = new DiamondTouchStreamProvider();
		System.loadLibrary("jdt");
		List<TouchDeviceInfo> infos = new ArrayList<TouchDeviceInfo>();
		
		registeredStreams = new HashMap<TouchDeviceInfo, TouchStream>();
		
		long[] deviceIds = DtlibDevice.getDeviceIds();

		for(long deviceId : deviceIds) {
			DtlibDevice device = DtlibDevice.getDevice(deviceId);

			device.start(DtlibInputTframe.getClassInputclass());
			DtlibInputTframe[] input;
			final int x;
			final int y;
			final int users;
			try {
				input = (DtlibInputTframe[]) device.read();
				x = input[0].getColLimit() * DtlibInputTframe.INTERPOLATION_FACTOR;
				y = input[0].getRowLimit() * DtlibInputTframe.INTERPOLATION_FACTOR;

				users = input.length;

			} catch (DtlibException e) {
				continue;
			} finally {
				device.stop();
			}

			DiamondTouchDeviceInfo info = new DiamondTouchDeviceInfo(users, new Dimension(x, y), Long.toString(device.getId()));

			infos.add(info);
			registeredStreams.put(info, new DiamondTouchStream(device, info));
		}
		
		touchDeviceInfos = Collections.unmodifiableList(infos);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<TouchDeviceInfo> getTouchDeviceInfoList() {
		return DiamondTouchStreamProvider.touchDeviceInfos;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public TouchStream getTouchStream(TouchDeviceInfo deviceInfo) {
		if(registeredStreams.containsKey(deviceInfo)) {
			return registeredStreams.get(deviceInfo);
		}
		return null;
	}

}
